//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2005-2007
//
// OziExplorer RTE (routes) export.
//

# include "StdAfx.h"
# include "Save.h"
# include "Map.h"
# include "Status.h"
# include "SaveFileDlg.h"
# include "FileWriter.h"
# include "fast_floor.h"
# include "Globals.h"

class COziRteExport : public CMapSaver {
  public:
	virtual bool CanSave (const map_t & _map) {return true;}
	virtual bool Save (HANDLE _hFile, const char * _strFileName, const map_t & _map);

  private:
	bool _Save (HANDLE _hFile, const map_t & _map);
};

DECLARE_WPTRK_EXPORT (COziRteExport, "ozi-rte", "rte", "OziExplorer routes (*.rte)");

bool COziRteExport::Save (HANDLE _hFile, const char * _strFileName, const map_t & _map) {
	if (_hFile) {
		return _Save (_hFile, _map);
	} else {
		//
		// Prepare default file name.
		//
		char strFileName [MAX_PATH + 1];
		::strncpy (strFileName, _strFileName, MAX_PATH);
		strFileName [MAX_PATH] = '\0';
		if (! SaveFileDlg ("rte", "OziExplorer routes (*.rte)\0*.rte\0", strFileName))
			return false;

		//
		// Open the file.
		//
		const CFileForWrite hFile (strFileName);
		if (! hFile.IsValid ()) {
			ErrorMsgBox ("Can't create file:\n %s", strFileName);
			return false;
		}

		return _Save (hFile, _map);
	}
}

bool COziRteExport::_Save (HANDLE _hFile, const map_t & _map) {
	CFileWriter fw (_hFile);
	fw.SetFPrecision (6);

	//
	// Write the file.
	//
	SetProgressStatus (0);

	fw.WriteS (
		"OziExplorer Route File Version 1.0\r\n"
		"WGS 84\r\n"
		"Reserved 1\r\n"
		"Reserved 2\r\n"
	);

	size_t cRoute = 0;
	size_t cOrdinal = 0;

	size_t cRgn = 0;
	const layer_t & layer = _map.layers [rkPolyline];
	const rgns_t & rgns = layer.rgns;
	for (rgns_t::const_iterator iRgn = rgns.begin (); iRgn != rgns.end (); ++ iRgn, ++ cRgn) {
		const rgn_t & rgn = * iRgn;
		if (rgn.IsDeleted () || ! rgn.IsRoute ())
			continue;

		// Save route.
		if (rgn.elements.empty ())
			continue;
		const rgn_element_t & element = rgn.elements [0];
		if (element.bDeleted)
			continue;

		const route_info_t * const pExtra = rgn.pExtra ? rgn.pExtra->wtr.route () : NULL;
		if (pExtra == NULL)
			continue;
		const size_t cPoints = pExtra->points.size ();

		// Route index.
		fw.WriteS ("R,");
		fw.WriteU (cRoute);
		fw.WriteC (',');

		// Route name.
		fw.WriteS (rgn.strLabel);
		fw.WriteC (',');

		// Route description.
		fw.WriteS (rgn.strComment);
		fw.WriteC (',');

		// Route color.
		if (pExtra->wFlags & route_info_t::defLineColor)
			fw.WriteU (pExtra->colLine);

		fw.WriteS ("\r\n");

		for (size_t cPoint = 0; cPoint < cPoints; ++ cPoint) {
			const routepoint_info_t & rpoint = pExtra->points [cPoint];
			const rgn_t * const pWpt = rpoint.pWaypoint;
			if (pWpt == NULL)
				continue;

			const rgn_origin_t & origin = pWpt->origins [0];
			assert (origin.bDeleted == false);

			const waypoint_info_t * const pWptExtra = pWpt->pExtra->wtr.wpt ();
			assert (pWptExtra);

			// Waypoint index.
			fw.WriteS ("W,");
			fw.WriteU (cRoute);
			fw.WriteC (',');
			fw.WriteU (cPoint + 1);
			fw.WriteC (',');
			fw.WriteU (cOrdinal);
			fw.WriteC (',');

			// Name.
			if (! pWpt->strLabel.empty ()) {
				for (size_t c = 0; c < pWpt->strLabel.size (); ++ c) {
					const char ch = pWpt->strLabel [c];
					fw.WriteC (ch == ',' ? 209 : ch);
				}
			} else
				fw.WriteU (cOrdinal);
			fw.WriteC (',');

			// Coordinates.
			fw.WriteF (origin.point.y);
			fw.WriteC (',');
			fw.WriteF (origin.point.x);
			fw.WriteC (',');

			// Time.
			if (pWptExtra->wFlags & waypoint_info_t::defTime)
				fw.WriteDF (pWptExtra->dtTime);
			else
				fw.WriteS (" ");
			fw.WriteC (',');

			// Symbol, Status, Display format.
			fw.WriteS ("0,1,3,");

			// Fg color.
			if (pWptExtra->wFlags & waypoint_info_t::defTextColor)
				fw.WriteU (pWptExtra->colText);
			else
				fw.WriteC ('0');
			fw.WriteC (',');

			// Bg color.
			if (pWptExtra->wFlags & waypoint_info_t::defBackColor)
				fw.WriteU (pWptExtra->colBack);
			else
				fw.WriteS ("65535");
			fw.WriteC (',');

			// Description.
			for (size_t c = 0; c < pWpt->strComment.size () && c < 40; ++ c) {
				const char ch = pWpt->strComment [c];
				fw.WriteC (ch == ',' ? 209 : ch);
			}

			// Pointer Direction, Garmin Display Format
			fw.WriteS (",0,0,");

			fw.WriteS ("\r\n");

			++ cOrdinal;
		}

		++ cRoute;

		SetProgressStatus (fast_floor (100.f*cRgn/layer.cRgns + .5f));
	}
	
	// TODO: complete up to 50th route??

	fw.FlushBuffer ();

	SetProgressStatus (100);

	if (fw.GetOverflow ())
		ErrorMsgBox ("File has been written partialy.\nThis may be caused by disk overflow.");

	return true;
}